.TH std::static_pointer_cast,std::dynamic_pointer_cast,std::const_pointer_cast, 3 "2024.06.10" "http://cppreference.com" "C++ Standard Libary"
.SH NAME
std::static_pointer_cast,std::dynamic_pointer_cast,std::const_pointer_cast, \- std::static_pointer_cast,std::dynamic_pointer_cast,std::const_pointer_cast,

.SH Synopsis

   Defined in header <memory>
   template< class T, class U >
   std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>&  \fB(1)\fP \fI(since C++11)\fP
   r ) noexcept;
   template< class T, class U >
   std::shared_ptr<T> static_pointer_cast( std::shared_ptr<U>&& r )   \fB(2)\fP \fI(since C++20)\fP
   noexcept;
   template< class T, class U >
   std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& \fB(3)\fP \fI(since C++11)\fP
   r ) noexcept;
   template< class T, class U >
   std::shared_ptr<T> dynamic_pointer_cast( std::shared_ptr<U>&& r )  \fB(4)\fP \fI(since C++20)\fP
   noexcept;
   template< class T, class U >
   std::shared_ptr<T> const_pointer_cast( const std::shared_ptr<U>& r \fB(5)\fP \fI(since C++11)\fP
   ) noexcept;
   template< class T, class U >
   std::shared_ptr<T> const_pointer_cast( std::shared_ptr<U>&& r )    \fB(6)\fP \fI(since C++20)\fP
   noexcept;
   template< class T, class U >
   std::shared_ptr<T> reinterpret_pointer_cast( const                 \fB(7)\fP \fI(since C++17)\fP
   std::shared_ptr<U>& r ) noexcept;
   template< class T, class U >
   std::shared_ptr<T> reinterpret_pointer_cast( std::shared_ptr<U>&&  \fB(8)\fP \fI(since C++20)\fP
   r ) noexcept;

   Creates a new instance of std::shared_ptr whose stored pointer is obtained from r's
   stored pointer using a cast expression.

   If r is empty, so is the new shared_ptr (but its stored pointer is not necessarily
   null). Otherwise, the new shared_ptr will share ownership with the initial value of
   r, except that it is empty if the dynamic_cast performed by dynamic_pointer_cast
   returns a null pointer.

   Let Y be typename std::shared_ptr<T>::element_type, then the resulting
   std::shared_ptr's stored pointer will be obtained by evaluating, respectively:

   1,2) static_cast<Y*>(r.get())
   3,4) dynamic_cast<Y*>(r.get()). If the result of the dynamic_cast is a null pointer
   value, the returned shared_ptr will be empty.
   5,6) const_cast<Y*>(r.get())
   7,8) reinterpret_cast<Y*>(r.get())

   The behavior of these functions is undefined unless the corresponding cast from U*
   to T* is well formed:

   1,2) The behavior is undefined unless static_cast<T*>((U*)nullptr) is well formed.
   3,4) The behavior is undefined unless dynamic_cast<T*>((U*)nullptr) is well formed.
   5,6) The behavior is undefined unless const_cast<T*>((U*)nullptr) is well formed.
   7,8) The behavior is undefined unless reinterpret_cast<T*>((U*)nullptr) is well
   formed.

   After calling the rvalue overloads (2,4,6,8), r is empty and r.get()
   == nullptr, except that r is not modified for dynamic_pointer_cast \fB(4)\fP \fI(since C++20)\fP
   if the dynamic_cast fails.

.SH Parameters

   r - the pointer to convert

.SH Notes

   The expressions std::shared_ptr<T>(static_cast<T*>(r.get())),
   std::shared_ptr<T>(dynamic_cast<T*>(r.get())) and
   std::shared_ptr<T>(const_cast<T*>(r.get())) might seem to have the same effect, but
   they all will likely result in undefined behavior, attempting to delete the same
   object twice!

.SH Possible implementation

                                   static_pointer_cast
   template<class T, class U>
   std::shared_ptr<T> static_pointer_cast(const std::shared_ptr<U>& r) noexcept
   {
       auto p = static_cast<typename std::shared_ptr<T>::element_type*>(r.get());
       return std::shared_ptr<T>{r, p};
   }
                                  dynamic_pointer_cast
   template<class T, class U>
   std::shared_ptr<T> dynamic_pointer_cast(const std::shared_ptr<U>& r) noexcept
   {
       if (auto p = dynamic_cast<typename std::shared_ptr<T>::element_type*>(r.get()))
           return std::shared_ptr<T>{r, p};
       else
           return std::shared_ptr<T>{};
   }
                                   const_pointer_cast
   template<class T, class U>
   std::shared_ptr<T> const_pointer_cast(const std::shared_ptr<U>& r) noexcept
   {
       auto p = const_cast<typename std::shared_ptr<T>::element_type*>(r.get());
       return std::shared_ptr<T>{r, p};
   }
                                reinterpret_pointer_cast
   template<class T, class U>
   std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U>& r) noexcept
   {
       auto p = reinterpret_cast<typename std::shared_ptr<T>::element_type*>(r.get());
       return std::shared_ptr<T>{r, p};
   }

.SH Example


// Run this code

 #include <iostream>
 #include <memory>

 class Base
 {
 public:
     int a;
     virtual void f() const { std::cout << "I am base!\\n"; }
     virtual ~Base() {}
 };

 class Derived : public Base
 {
 public:
     void f() const override { std::cout << "I am derived!\\n"; }
     ~Derived() {}
 };

 int main()
 {
     auto basePtr = std::make_shared<Base>();
     std::cout << "Base pointer says: ";
     basePtr->f();

     auto derivedPtr = std::make_shared<Derived>();
     std::cout << "Derived pointer says: ";
     derivedPtr->f();

     // static_pointer_cast to go up class hierarchy
     basePtr = std::static_pointer_cast<Base>(derivedPtr);
     std::cout << "Base pointer to derived says: ";
     basePtr->f();

     // dynamic_pointer_cast to go down/across class hierarchy
     auto downcastedPtr = std::dynamic_pointer_cast<Derived>(basePtr);
     if (downcastedPtr)
     {
         std::cout << "Downcasted pointer says: ";
         downcastedPtr->f();
     }

     // All pointers to derived share ownership
     std::cout << "Pointers to underlying derived: "
               << derivedPtr.use_count()
               << '\\n';
 }

.SH Output:

 Base pointer says: I am base!
 Derived pointer says: I am derived!
 Base pointer to derived says: I am derived!
 Downcasted pointer says: I am derived!
 Pointers to underlying derived: 3

.SH See also

   constructor   constructs new shared_ptr
                 \fI(public member function)\fP
